import logging
import random
import re
import time

from django.contrib.auth import authenticate
from django.core.cache import cache
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken

from users.models import User

# Create your views here.

logger = logging.getLogger('apps')


class LoginView(APIView):
    """
    用户名/密码登录:
    1:接受从前端传过来的用户名和密码
    2:参数验证是否为空
    3:验证用户名和密码是否正确
    4:验证失败:提示用户名和密码不正确
    5:验证成功:生成token

    """

    def post(self, request):
        try:
            # 1:接受从前端POST传过来的用户名和密码
            username = request.data.get("username")
            password = request.data.get("password")

            # 2:参数验证是否为空
            if not all([username, password]):
                return Response({
                    "code": 0,
                    "message": "用户名和密码不能为空"
                })

            # 3: 验证用户名和密码是否正确
            user = authenticate(username=username, password=password)

            if not user:
                logger.error(f"用户登录失败哦,用户名:{username}")
                return Response({
                    "code": 0,
                    "message": "用户名或密码错误"
                })

            # 5:验证成功:生成token
            refresh = RefreshToken.for_user(user)
            print(type(refresh))
            # 访问token:access_token,续期token:refresh_token

            logger.info(f"用户登录成功,用户名:{username}")

            return Response({
                "code": 1,
                "message": "登录成功",
                "data": {
                    "token": str(refresh.access_token),
                    "refresh": str(refresh),
                    "username": username,
                    "userId": user.id

                }

            })


        except Exception as e:
            logger.error()
            return Response({
                "code": 0,
                "message": f"登录失败:{str(e)}"
            })


class SendSmsCodeView(APIView):
    def post(self, request):
        try:
            # 1:接受手机号参数
            mobile = request.data.get("mobile", "")

            # 场景,登录:login  注册:register
            scene = request.data.get("scene", "login")  # 默认为登录场景
            # 2:验证手机号格式
            if not re.match(r"^1[3-9]\d{9}$", mobile):
                return Response({
                    "code": 0,
                    "message": "手机号格式错误"
                })
            # 3:业务校验
            # 3.1:手机号是否注册
            if scene == "login":
                if not User.objects.filter(mobile=mobile).exists():
                    return Response({
                        "code": 0,
                        "message": "手机号未注册"
                    })
            elif scene == "register":
                if User.objects.filter(mobile=mobile).exists():
                    return Response({
                        "code": 0,
                        "message": "手机号已被注册"
                    })

            # 3.2:发送频率限制
            # 获取上次发送的时间
            last_send_time_key = f"users:login:sms_last_send:{mobile}"
            last_send_time = cache.get(last_send_time_key)
            now = time.time()
            if last_send_time and now - last_send_time < 60:
                remaining = int(60 - (now - last_send_time))
                return Response({
                    "code": 0,
                    "message": f"请{remaining}秒重试"
                })

            # 4:生成验证码
            sms_code = ''.join(random.choices('0123456789', k=6))

            # 5:缓存到redis
            sms_code_key = f"users:login:sms_code:{mobile}"

            # 缓存验证码,有效期5分钟
            cache.set(sms_code_key, sms_code, timeout=300)

            user = User.objects.get(mobile=mobile)
            logger.info(f"向邮箱号{user.email}发送验证码")

            from .tasks import send_verification_email
            send_verification_email(user.email, sms_code)
            logger.info(f"向邮箱{user.email}发送验证码:{sms_code}")
            # 模拟发送验证码的接口
            logger.info(f"向手机号{mobile}发送验证码:{sms_code}")

            # 记录本次发送短信的时间
            cache.set(last_send_time_key, now, timeout=60)

            return Response({
                "code": 1,
                "msg": "短信发送成功"
            })

        except Exception as e:
            logger.error(e)
            return Response({
                "code": 0,
                "msg": f"短信发送失败:{str(e)}"
            })


class MobileLoginView(APIView):
    def post(self, request):
        try:

            # 1. 接收参数
            mobile = request.data.get("mobile", "")
            sms_code = request.data.get("code", "")
            # 2:验证手机号格式
            if not re.match(r"^1[3-9]\d{9}$", mobile):
                return Response({
                    "code": 0,
                    "message": "手机号格式错误"
                })
                # 3:手机号是否注册
            if not User.objects.filter(mobile=mobile).exists():
                return Response({
                    "code": 0,
                    "message": "手机号未注册"
                })

            sms_code_key = f"users:login:sms_code:{mobile}"

            # 验证码校验
            cached_code = cache.get(sms_code_key)
            if not cached_code:
                return Response({
                    "code": 0,
                    "message": "验证码已过期"
                })

            if cached_code != sms_code:
                return Response({
                    "code": 0,
                    "message": "验证码错误"
                })
            # 验证通过，清除验证码缓存
            cache.delete(sms_code_key)
            user = User.objects.get(mobile=mobile)
            # 生成token
            refresh = RefreshToken.for_user(user)
            logger.info(f"用户登录成功,手机号:{mobile}")

            return Response({
                "code": 1,
                "message": "登录成功",
                "data": {
                    "token": str(refresh.access_token),
                    "refresh": str(refresh),
                    "username": user.username,
                    "userId": user.id

                }

            })
        except Exception as e:
            logger.error(f"用户登录失败,手机号:{mobile},错误信息:{e}")
            return Response({
                "code": 0,
                "message": f"登录失败:{str(e)}",
            })


class UserRegisterView(APIView):
    def post(self, request):
        try:
            # 1. 接收参数
            username = request.data.get("username")
            password = request.data.get("password")
            mobile = request.data.get("mobile")
            code = request.data.get("code")
            if not all([username, password, mobile, code]):
                return Response({
                    "code": 0,
                    "message": "参数不完整"
                })

            # 验证手机号格式
            if not re.match(r"^1[3-9]\d{9}$", mobile):
                return Response({
                    "code": 0,
                    "message": "手机号格式错误"
                })

            # 验证手机号是否重复
            if User.objects.filter(mobile=mobile).exists():
                return Response({
                    "code": 0,
                    "message": "手机号已注册"
                })

            if len(password) < 6:
                return Response({
                    "code": 0,
                    "message": "密码长度不能小于6位"
                })
            if len(password) > 20:
                return Response({
                    "code": 0,
                    "message": "密码长度不能大于20位"
                })

            # 至少包含数字和字母
            if not re.search(r"[0-9]", password) or not re.search(r"[a-zA-Z]", password):
                return Response({
                    "code": 0,
                    "message": "密码至少包含数字和字母"
                })

                # 5:缓存到redis
            sms_code_key = f"users:login:sms_code:{mobile}"

            cache_code = cache.get(sms_code_key)

            if code != cache_code:
                return Response({
                    "code": 0,
                    "message": "验证码错误"
                })

            # 创建用户.(注册)
            user = User.objects.create_user(
                username=username,
                password=password,
                mobile=mobile
            )
            cache.delete(sms_code_key)

            refresh = RefreshToken.for_user(user)
            return Response({
                "code": 1,
                "message": "注册成功",
                "data": {
                    "token": str(refresh.access_token),
                    "refresh_token": str(refresh),
                    "username": user.username,
                    "userId": user.id,
                    "mobile": user.mobile
                }
            })

        except Exception as e:
            return Response({
                "code": 0,
                "message": "注册失败",
                "data": str(e)
            })
